/*


    作业: 配置多个按键key1,key2,key3 ，并且注册中断号，一个中断isr函数区分
配置一个按键： 
大板: rk3399-nanopi4-rev07.dts
/ {
	...
	
	key1_button {
		compatible = "rk3399,key1-button";
		gpios = <&gpio1 1 IRQ_TYPE_EDGE_BOTH>; //GPIO1_A1
		pinctrl-names = "default";
		pinctrl-0 = <&button_k1_gpio>;
	};
	...
};

&pinctrl {
	key1_button {
		button_k1_gpio:button_k1_gpio {
			rockchip,pins = <1 1 RK_FUNC_GPIO &pcfg_pull_up>;
		};
	};
	...

};


配置多个按键： 

/ {
	model = "FriendlyElec SOM-RK3399";
	compatible = "friendlyelec,som-rk3399", "rockchip,rk3399";

// my devicetree node
	xydnode3399 {
		
//配置3个按键
  	//add k1
	key1_button {
		compatible = "rk3399,key1-button";
		gpios = <&gpio1 1 IRQ_TYPE_EDGE_BOTH>; //GPIO1_A1
		gpios3 = <&gpio1 3 IRQ_TYPE_EDGE_BOTH>; //GPIO1_A3
		gpios4 = <&gpio1 4 IRQ_TYPE_EDGE_BOTH>; //GPIO1_A4
		pinctrl-names = "default";
		pinctrl-0 = <&button_k1_gpio>;
	};
};

&pinctrl {
#if 0
	key1_button {
		button_k1_gpio:button_k1_gpio {
			rockchip,pins = <1 1 RK_FUNC_GPIO &pcfg_pull_up>;
		};
	};
#endif
#if 1
	key1_button {
		button_k1_gpio:button_k1_gpio {
			rockchip,pins = <1 1 RK_FUNC_GPIO &pcfg_pull_up>,
			<1 3 RK_FUNC_GPIO &pcfg_pull_up>,
			<1 4 RK_FUNC_GPIO &pcfg_pull_up>;
		};
	};
#endif
};


*/


#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h> // of				
#include <linux/of_gpio.h> //gpio	
#include <linux/gpio.h>	
#include <dt-bindings/gpio/gpio.h>
#include <linux/interrupt.h>

static int gpio_button;
static int irqno;

static int gpio_button2;
static int irqno2;


static int gpio_button3;
static int irqno3;

//定义中断处理函数

static irqreturn_t button_handler(int irqno, void *dev_id)
{

	 const char *dev_name = (const char *)dev_id;	
	 printk("irqno=%d ,dev_name= %s()\n", irqno, dev_name); 

     return IRQ_HANDLED;
}



//当平台驱动和平台设备匹配时调用probe函数
static int button_probe(struct platform_device *pdev)
{
	int ret;
	
	//获得匹配的device_node对象, 然后拿设备节点下硬件数据
	struct device_node *button_ctrl_node = pdev->dev.of_node;

	printk("<kernel> call：  %s()\n", __func__);  

	gpio_button = of_get_named_gpio(button_ctrl_node, "gpios", 0);
	if (gpio_is_valid(gpio_button)) {
		printk("gpio_button=%d\n", gpio_button);
	} else {
		printk("of_get_named_gpio_flags fail\n");
		return -EINVAL;
	}
	//获取中断号
	irqno = gpio_to_irq(gpio_button);
	printk("irqno=%d\n", irqno);
	ret = request_irq(irqno, button_handler, IRQ_TYPE_EDGE_BOTH, "key1_int", "key1");
	if (ret) {
		gpio_free(gpio_button);
		printk("request_irq fail\n");
		return -EFAULT;
	}



	gpio_button2 = of_get_named_gpio(button_ctrl_node, "gpios3", 0);
	if (gpio_is_valid(gpio_button2)) {
		printk("gpio_button2=%d\n", gpio_button2);
	} else {
		printk("of_get_named_gpio_flags fail\n");
		return -EINVAL;
	}
	//获取中断号
	irqno2 = gpio_to_irq(gpio_button2);
	printk("irqno2=%d\n", irqno2);
	ret = request_irq(irqno2, button_handler, IRQ_TYPE_EDGE_BOTH, "key2_int", "key2");
	if (ret) {
		gpio_free(gpio_button2);
		printk("request_irq fail\n");
		return -EFAULT;
	}



	gpio_button3 = of_get_named_gpio(button_ctrl_node, "gpios4", 0);
	if (gpio_is_valid(gpio_button3)) {
		printk("gpio_button3=%d\n", gpio_button3);
	} else {
		printk("of_get_named_gpio_flags fail\n");
		return -EINVAL;
	}
	//获取中断号
	irqno3 = gpio_to_irq(gpio_button3);
	printk("irqno3=%d\n", irqno3);
	ret = request_irq(irqno3, button_handler, IRQ_TYPE_EDGE_BOTH, "key3_int", "key3");
	if (ret) {
		gpio_free(gpio_button3);
		printk("request_irq3 fail\n");
		return -EFAULT;
	}



	return 0;
}

//当平台驱动和平台设备分离时调用remove函数
static int button_remove(struct platform_device *pdev)
{
	free_irq(irqno, NULL);
	gpio_free(gpio_button);


	free_irq(irqno2, NULL);
	gpio_free(gpio_button2);

	free_irq(irqno3, NULL);
	gpio_free(gpio_button3);

	printk("<kernel> call %s()\n", __func__);  
	return 0;

}

static const struct platform_device_id button_id_table[] = {
	{
		.name = "rk3399_button",
		.driver_data = 0x1,
	}, {
		.name = "rk3288_button",
		.driver_data = 0x2,
	}, {
		.name = "rk3568_button",
		.driver_data = 0x3,
	}, {
		/* id table */
	}
};

static const struct of_device_id button_of_match[] = {
	{ .compatible = "rk3399,key1-button", },  //必须和设备树节点的compatible属性匹配
	{ /*of match table*/ }
};


//定义平台驱动对象并初始化
static struct platform_driver rk_button_driver = {
	.probe		= button_probe,
	.remove		= button_remove,
	.driver		= {
		.name	= "rk_button", //平台驱动的字符串名称
		.of_match_table = button_of_match, //指向匹配设备树节点的数组
	},
	.id_table = button_id_table, //指向匹配平台设备的数组
};



static int __init driver_mod_init(void)
{
	printk("<kernel> call %s()\n", __func__);  
	return platform_driver_register(&rk_button_driver);
}


static void __exit driver_mod_exit(void)
{
	printk("<kernel> call %s() @ %d\n", __FUNCTION__, __LINE__);  
	platform_driver_unregister(&rk_button_driver);
}


module_init(driver_mod_init); 
module_exit(driver_mod_exit); 
MODULE_LICENSE("GPL"); 



